package drds.plus.executor.command_handler.put;

import drds.plus.executor.ExecuteContext;
import drds.plus.executor.ExecutorException;
import drds.plus.executor.function.scalar.ScalarFunction;
import drds.plus.executor.record_codec.RecordCodecFactory;
import drds.plus.executor.record_codec.record.Record;
import drds.plus.executor.table.ITable;
import drds.plus.executor.utils.Utils;
import drds.plus.sql_process.abstract_syntax_tree.configuration.ColumnMetaData;
import drds.plus.sql_process.abstract_syntax_tree.configuration.IndexMapping;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.dml.IPut;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.dml.PutType;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.Function;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.function.FunctionType;

import java.util.List;

public class ReplaceHandler extends PutHandler {

    public ReplaceHandler() {
        super();
    }

    protected int executePut(ExecuteContext executeContext, IPut put, ITable table, IndexMapping indexMapping) throws Exception {
        int affectRows = 0;
        Record keyRecord = RecordCodecFactory.newRecordCodec(indexMapping.getKeyColumnMetaDataList()).newRecord();
        Record valueRecord = RecordCodecFactory.newRecordCodec(indexMapping.getValueColumnMetaDataList()).newRecord();
        List<Item> itemList = put.getUpdateItemList();
        L:
        for (int i = 0; i < itemList.size(); i++) {
            for (ColumnMetaData columnMetaData : indexMapping.getKeyColumnMetaDataList()) {
                if (columnMetaData.getColumnName().equals(Utils.getColumn(itemList.get(i)).getColumnName())) {
                    Object object = put.getUpdateValues().get(i);
                    if (object != null) {
                        if (object instanceof Function) {
                            if (((Function) object).getFunctionType().equals(FunctionType.aggregate_function)) {
                                throw new ExecutorException("replace is not support aggregate_function function");
                            }
                            Function function = ((Function) object);
                            object = ((ScalarFunction) function.getExtraFunction()).scalarCalucate(executeContext, null);
                        }
                    }
                    keyRecord.put(columnMetaData.getColumnName(), object);
                    continue L;
                }
            }
            for (ColumnMetaData columnMetaData : indexMapping.getValueColumnMetaDataList()) {
                if (columnMetaData.getColumnName().equals(Utils.getColumn(itemList.get(i)).getColumnName())) {
                    Object object = put.getUpdateValues().get(i);
                    valueRecord.put(columnMetaData.getColumnName(), object);
                    break;
                }
            }
        }
        if (put.getPutType() == PutType.insert) {
            Record value1 = table.get(executeContext, put.getTableName(), indexMapping, keyRecord);
            if (value1 != null) {
                throw new ExecutorException("Duplicate_entry :" + keyRecord);
            }
        }
        table.put(executeContext, put.getTableName(), indexMapping, keyRecord, valueRecord);
        affectRows++;
        return affectRows;

    }

}
